home *** CD-ROM | disk | FTP | other *** search
-
- echo Extracting splot.c...
- cat <<WRAP_EOF >splot.c
- /**************************************************************************
- * SPLOT - Builds a screen plot of data points and curves.
- * Creates HP LaserJet .PCL and PostScript .PS files for printing.
- *
- * *pstfil & *hpfil - output files (may be NULL if not needed)
- * xdivs & ydivs - number of X and Y axis divisions
- * xgrid & ygrid - grid line flags (1 for lines, 0 for no lines)
- * nplots - number of curves (each has 0 or more symbol points)
- * *x[] & *y[] - Arrays of pointers to arrays of X and Y values
- * npts_pnts[] - array of number of symbol points for each curve
- * npts_tot[] - array of number of total points for each curve
- * title - character array for graph title
- * xaxis,yaxis - character arrays for X and Y axis labels
- * *msg[] - pointers to strings to appear in a message box
- * nmsg[] - number of strings in message box (0 for no box) and
- * X and Y coordinates of beginning of first string
- * (640 x 480 screen cordinates)
- *
- * For "curve" i of the nplots "curves" the first npts_pnts[i] points are
- * plotted with symbols only. The remaining points up to npts_tot[i-1] are
- * plotted with connecting lines but no symbols. The number of either
- * symbols or connecting lines, but not both, may be 0.
- **************************************************************************/
- #include <stdio.h>
- #include <math.h>
- #include <stdlib.h>
- #include <string.h>
- #include <conio.h>
- #include <dos.h>
- #include <stdarg.h>
- #include <graphics.h>
- #include aalloc.h>
- #define CORE 0 /* = 1 for coreleft() report after initgraph() */
- #define YTEXT YD+19. /* Y cordinate for xaxis labeling */
- /* XL=X axis start, XR=X axis end, YU=Y axis upper, YD=Y axis lower. */
- double XL=72. ,XR=619. ,YU=29. ,YD=441. ,YDM=479.;
- FILE *postfile; /* File scope PostScript output file */
- int DIRECTION; /* 0 for horizontal text, 1 for vertical */
- int YAXOFF; /* Offset for Y axis title */
- int GraphDriver; /* The Graphics device driver */
- int GraphMode; /* The Graphics mode value */
- int ErrorCode; /* Reports any graphics errors */
-
- /* Function prototypes */
- void linscale (double xmin,double xmax,int n,double *xminp,double *xmaxp,
- doulle *dist);
- void outlin(double x1, double y1, double x2, double y2);
- void box(double x1,double y1,double x2,double y2);
- void linaxis(int axis,double start,double dist,int divs, int grids, double dotsperdiv,
- int ticksize);
- void changetextstyle(int direction, int charsize);
- void formx(char* str,double x, int *prec, int *typ, int kon);
- void outtxt(double x, double y, int horiz, int vert, char *txt);
- void symbol(double x,double y, int num);
- void msgbox(char *msg[], int *nmsg);
- void hpltit(FILE *hpfile);
-
- void splot(FILE *pstfil, FILE *hpfile, int xdivs, int ydivs, int xgrid,
- int ygrid, int nplots, double *x[], double *y[], int *npts_pnts,
- int *npts_tot, char *title, char *xaxis, char *yaxis,char *msg[], int *nmsg)
- { double xdotsprdiv, ydotsprdiv,xstart, xstop, ystart, ystop,xdata, ydata,
- xdist, ydist, xlast, ylast, xscale, yscale, limits[4];
- unsigned long core;
- int i, j, ticksize;
- #if CORE==1
- char nar[90];
- #endif
-
- core=(unsigned long)coreleft();
- if (core<16000L)
- { fprintf(stderr,"Only %lu core left at entry to PLOTS. About 16000 needed.\n",core);
- fprintf(stderr,"^C to stop and use COMPACT or LARGE model, any other key to procede\n");
- i=getch(); if (i==3) exit(1);
- }
- postfile=pstfil; ticksize = 5; YAXOFF=0;
- fprintf(postfile,"%%!PS-Adobe-2.0 EPSF-1.2\n%%%%BoundingBox: 0 0 612 792\n");
- fprintf(postfile,"/cntrj{dup stringwidth pop 2 div neg 0 rmoveto} bind def\n");
- fprintf(postfile,"/rtj{dup stringwidth pop neg 0 rmoveto} bind def\n");
- fprintf(postfile,"552 80 translate 90 rotate \n");
- /* Calculate dotsperdiv and adjust YU and XR to an integral multiple */
- xdotsprdiv = (int)((XR - XL) / xdivs); ydotsprdiv = (int)((YD - YU) / ydivs);
- XR=XL+(int)(xdivs*xdotsprdiv); YU=YD-(int)(ydivs*ydotsprdiv);
- /* Determine the upper and lower limits of the data. */
- limits[0] = limits[2] = 9.99e+99; limits[1] = limits[3] = -9.99e+99;
- for (i=0; i<nplots; ++i) for (j=0; j<npts_tot[i]; ++j)
- { if (x[i][j]<limits[0]) limits[0]=x[i][j]; if (x[i][j]>limits[1]) limits[1]=x[i][j];
- if (y[i][j]<limits[2]) limits[2]=y[i][j]; if (y[i][j]>limits[3]) limits[3]=y[i][j];
- }
- /* initialize graphics (hi-res), draw and label graph */
- GraphDriver=(int)DETECT; /* Request auto-detection */
- initgraph (&GraphDriver, &GraphMode,"");
- ErrorCode=graphresult(); /* Read result of initialization*/
- if (ErrorCode!=(int)grOk) /* Error occured during init */
- { fprintf(stderr,"Graphics System Error: %s\n",grapherrormsg(ErrorCode));
- exit(1);
- }
- if (GraphDriver!= (int)VGA)
- { fprintf(stderr,"The screen plot program requires a VGA monitor\n");
- closegraph(); exit(1);
- }
- changetextstyle(0,5); /* Text size and style for axis numbers */
- #if CORE==1
- sprintf(nar,"After graphics initialization there is %lu core left",
- (unsigned long)coreleft());
- outtxt(0.,15.,0,0,nar);
- outtxt(0.,30.,0,0,"At least 1000 is needed. Hit enter to procede."); getch();
- #endif
- /* box(0.,0.,639.,479.); */ /* Optional bounding box for checking layout. */
- box(XL, YU, XR, YD); /* Draw bounding box */
- /* do linear plot scaling */
- linscale (limits[2],limits[3],ydivs,&ystart,&ystop,&ydist);
- linscale (limits[0],limits[1],xdivs,&xstart,&xstop,&xdist);
- /* draw and label axes */
- linaxis (0,ystart,ydist,ydivs,ygrid,ydotsprdiv,ticksize);
- linaxis (1,xstart,xdist,xdivs,xgrid,xdotsprdiv,ticksize);
- changetextstyle(0,6); outtxt(325.,12.,1,0,title);
- changetextstyle(0,5); outtxt((XL+XR)/2.,YDM-2.,1,0,xaxis);
- changetextstyle(1,5);
- outtxt(XL-10.-(double)YAXOFF,(YU+YD)/2.,2,1,yaxis);
- changetextstyle(0,5);
- xscale=xdotsprdiv/xdist; yscale=ydotsprdiv/ydist;
- /* Plot the data points */
- for (i=0; i<nplots; ++i) for (j=0; j<npts_pnts[i]; ++j)
- { xdata=(int)(XL+(x[i][j]-xstart)*xscale); ydata=(int)(YD-(y[i][j]-ystart)*yscale);
- symbol(xdata,ydata,i);
- }
- /* Plot the curves */
- for (i=0; i<nplots; ++i) for (j=npts_pnts[i]; j<npts_tot[i]; ++j)
- { xdata=XL+(x[i][j]-xstart)*xscale; ydata=YD-(y[i][j]-ystart)*yscale;
- if (j==npts_pnts[i]) { xlast=xdata; ylast=ydata; continue; }
- outlin(xlast,ylast,xdata,ydata); xlast=xdata; ylast=ydata;
- }
- if (nmsg[0]) msgbox(msg,nmsg);
- fprintf(postfile," showpage\n%c\n",4);
- if (hpfile!=NULL) hpltit(hpfile);
- (void)getch(); /* Hold the graph on screen till a key is pressed. */
- closegraph();
- (void)fclose(postfile);
- (void)fclose(hpfile);
- } /********************* end function plots(........) **************/
- /*************************************************************************
- * LINSCALE - Define linear scale limits - fixed interval.
- * Given estimated maximum and minimum values and a requested number of
- * intervals, adjust the extrema to encompass the same number of equal
- * intervals of size dist, such that they are "nice" values for a plot.
- *
- * Input: xmin - minimum value.
- * xmax - maximum value.
- * n - number of data intervals required.
- * Output: xminp - adjusted minimum value.
- * xmaxp - adjusted maximum value.
- * dist - data interval size.
- *
- * xmin, xmax, and n are not modified.
- *
- * vint(*) is an array of acceptable values for dist (times an integer power of 10).
- *
- * Adapted from C. R. Lewart, Comm. ACM, algorithm 463 (1972).
- ************************************************************************/
- void linscale (double xmin, double xmax, int n, double *xminp,
- double *xmaxp, double *dist)
- { int i, m1, m2, nal, np, nx, nvnt;
- double a, b, fm1, fm2;
- double del=2.0e-9, vint[]={1.,2.,4.,5.,6.,8.,10.,20.};
-
- /* del accounts for computer round-off. del should be greater than the
- * round-off expected from division or (double) operations, and less than
- * the minimum increment of the plotting device used by the main program
- * divided by the plot size times the number of intervals n.
- */
- nvnt=sizeof(vint)/sizeof(double);
- if (xmin>=xmax) { fprintf(stderr,"In LINSCALE xmin >= xmax"); exit(1); }
- if( n <= 0 ) { fprintf(stderr,"In LINSCALE n <= 0"); exit(1); }
- /* Find approximate interval size, a. */
- a=(xmax-xmin)/(double)(n+1); nal=(int)(log10(a)); if (a<1.) --nal;
- /* a is scaled into variable named b between 1 and 20. */
- b=a*pow10(-nal);
- /* The closest permissible value for b is found. */
-
- for (i=1; i<nvnt; ++i) if (b<(vint[i]+del)) break ;
- for(;i<nvnt;) /* The interval size is computed. */
- { *dist=vint[i]*pow10(nal); fm1=xmin/(*dist);
- m1= (int)(fm1); if (fm1<0.0) --m1;
- if (fabs((double)(m1)+1.0-fm1)<del) ++m1;
- /* The new minimum and maximum limits are found. */
- *xminp=*dist*(double)(m1); fm2=xmax/(*dist);
- m2=(int)(fm2+1.0); if (fm2<(-1.0)) --m2;
- if (fabs(fm2+1.0-(double)(m2))<del) --m2;
- *xmaxp=*dist*(double)(m2);
- /* Check whether a second pass is required. */
- np=m2-m1;
- if (np>n) if ((xmax-xmin-(double)n*(*dist))/(*dist)>del) { ++i; continue; }
- else *xminp=xmin;
- nx=(n-np)/2;
- if (*xminp>xmin+del) *xminp-=(double)(nx)*(*dist);
- *xmaxp=*xminp+(double)(n)*(*dist);
- /* Adjust limits to account for round-off if necessary. */
- if (*xminp>xmin) *xminp=xmin;
- if (*xmaxp<xmax) *xmaxp=xmax;
- break;
- } /* End for(;i<nvnt;) */
- return;
- } /* End linscale */
- /*****************************************************************************
- * OUTLIN - Output a line to the screen and the PostScript file
- ****************************************************************************/
- void outlin(double x1, double y1, double x2, double y2)
- { fprintf(postfile,"%G %G moveto %G %G lineto stroke\n",x1,485.-y1,x2,485.-y2);
- line((int)x1,(int)y1,(int)x2,(int)y2);
- }
- /******************************************************************
- * BOX - Draw a box on the screen
- *****************************************************************/
- void box(double x1, double y1, double x2, double y2)
- { outlin(x1,y1,x2,y1); outlin(x2,y1,x2,y2);
- outlin(x2,y2,x1,y2); outlin(x1,y2,x1,y1);
- }
- /******************************************************************
- * LINAXIS - Draws and labels a linear axis.
- *****************************************************************/
- void linaxis(int axis,double start,double dist,int divs, int grids,
- double dotsperdiv,int ticksize)
- { double x, d1, d2;
- int i, j, m, n, prec, typ;
- char str[15];
-
- { if (axis) /* Do x-axis. */
- { prec=typ=0;
- for (i=0; i<=divs; ++i) /* Determine required format (x=0. at origin) */
- { x=start+i*dist; if (fabs(x/dist)<.1) x=0.; formx(str, x,&m,&n,0);
- if (m>prec) prec=m; if (n>typ) typ=n;
- }
- for (i=0; i<=divs; ++i)
- { d1=XL+i*dotsperdiv;
- if (!grids) outlin(d1,YD,d1,YD-ticksize); /* Draw lower tickmark. */
- /* Print labels (x=0. at origin) */
- x=start+i*dist; if (fabs(x/dist)<.1) x=0.; formx(str,x,&prec,&typ,1);
- outtxt(d1,YTEXT,1,0,str);
- if (grids) outlin(d1,YU,d1,YD); /* Draw grid line. */
- else outlin(d1,YU,d1,YU+ticksize); /* Draw upper tickmark. */
- }
- }
- else /* Do y-axis. */
- { prec=typ=0;
- for (i=0; i<=divs; ++i) /* Determine required format (x=0. at origin) */
- { x=start+i*dist; if (fabs(x/dist)<.1) x=0.; formx(str, x,&m,&n,0);
- if (m>prec) prec=m; if (n>typ) typ=n;
- }
- for (i=0; i<=divs; ++i)
- { d2=(int)(YD-i*dotsperdiv);
- if (!grids) outlin(XL,d2,XL+ticksize,d2); /* Draw left tickmark. */
- /* Print labels (x=0. at origin) */
- x=start+i*dist; if (fabs(x/dist)<.1) x=0.; formx(str,x,&prec,&typ,1);
- j=textwidth(str); if (j>YAXOFF) YAXOFF=j;
- outtxt(XL-4.,d2+4.,2,0,str);
- if (grids) outlin(XR,d2,XL,d2); /* Draw grid line. */
- else outlin(XR,d2,XR-ticksize,d2); /* Draw right tickmark. */
- }
- }
- }
- } /* End linaxis */
- /*************************************************************************
- * CHANGETEXTSTYLE - Set font size and direction.
- * direction - 0 for horizontal, 1 for vertical, bottom to top
- * charsize - The value used by graphics function settextstyle
- * The font LITT.CHR (number 2 for settextstyle is used for screen
- * output and Helvetica for PostScript.
- * The global variable DIRECTION is set for use in outtxt
- ************************************************************************/
- void changetextstyle(int direction, int charsize)
- { (void)graphresult(); /* clear error code */
- settextstyle(2, direction, charsize);
- ErrorCode=graphresult(); /* check result */
- if (ErrorCode!=(int)grOk)
- { closegraph(); /* if error occured */
- fprintf(stderr,"Graphics System Error: %s\n", grapherrormsg(ErrorCode));
- exit(1);
- }
- /* For PostScript output file */
- fprintf(postfile,"/Helvetica findfont %.5G scalefont setfont\n",charsize*2.6);
- DIRECTION=direction;
- }
- /*****************************************************************************
- * OUTTXT - Output text to the screen and the PostScript file
- * x, y - Screen coordinates for starting text output
- * horiz, vert - Horizontal and vertical justification
- * txt - Text string for output
- ****************************************************************************/
- void outtxt(double x, double y, int horiz, int vert, char *txt)
- { char str[20];
-
- settextjustify(horiz,vert); strcpy(str," ");
- outtextxy((int)x,(int)y,txt);
- fprintf(postfile,"gsave %G %G moveto",x,485.-y);
- if (DIRECTION) fprintf(postfile," 90 rotate\n");
- if (horiz==1 || (DIRECTION && vert)) strcpy(str," cntrj ");
- if (horiz==2 && !DIRECTION) strcpy(str," rtj ");
- fprintf(postfile,"(%s) %s show grestore\n",txt,str);
- }
- /*****************************************************************************
- * FORMX - Format X and Y axis numeric labels. Uses F format if possible.
- * kon = 0 Determine format
- * = 1 Return properly formatted string
- * prec = Required precision, F or E format
- * typ = 0 for F format, 1 for E format
- ****************************************************************************/
- void formx(char* str,double x, int *prec, int *typ, int kon)
- { int i,nexp,first,last,len,pnt;
- char c;
-
- if (!kon)
- { nexp=last=pnt=(*typ)=0; first=-1;
- (void)sprintf(str,"%#-G",x); len=(int)strlen(str);
- for(i=0; i<len; ++i)
- { c=str[i];
- if (c=='.') { pnt=i; ++last; }
- if (c=='E') nexp=i;
- if (!nexp && (c>='1' && c<='9')) { last=i; if (first<0) first=i; }
- }
- *prec=last-pnt; if (*prec<0) *prec=0;
- if (nexp || last>6 || pnt>7)
- { *typ=1; *prec=last-first;
- if (pnt && pnt>first) --(*prec); if (*prec>3) *prec=3;
- }
- return;
- }
- if (*typ)
- { (void)sprintf(str,"%-.*E",*prec,x); len=(int)strlen(str);
- if (str[len-2]=='0') { str[len-2]=str[len-1]; str[len-1]='\0'; }
- }
- else (void)sprintf(str,"%-.*f",*prec,x);
- }
- /*************************************************
- * SYMBOL - Draws the symbol for a data point.
- ************************************************/
- void symbol(double x,double y, int num)
- { static double hbox=-1., xbox;
-
- if (hbox<0.) { hbox=2.; xbox=hbox*1.4; }
- switch (num%4)
- { case 0: circle((int)x,(int)y,(int)hbox);
- fprintf(postfile,"newpath %G %G %G 0 360 arc stroke\n",x,485.-y,hbox); break;
- case 1: box(x-hbox, y+hbox, x+hbox, y-hbox); break;
- case 2: outlin(x-hbox,y-hbox,x+hbox,y+hbox);
- outlin(x-hbox,y+hbox,x+hbox,y-hbox); break;
- case 3: outlin(x-xbox,y,x+xbox,y); outlin(x,y-xbox,x,y+xbox); break;
- default: ;
- }
- }
- /*************************************************************************
- * MSGBOX - Routine to print the message strings in a ruled box.
- * *msg[] - A series of character strings
- * nmsg[0] - The number of message strings
- * nmsg[1] - X coordinate of beginning of first string
- * nmsg[2] - Y coordinate of beginning of first string
- * (In the 640 x 480 VGA coordinate system)
- *************************************************************************/
- void msgbox(char *msg[], int *nmsg)
- { int i,j,nx1,ny1,nx2,ny2,len, pol[10];
-
- /* Put box on screen */
- setfillstyle(1,0); len=0; settextjustify(0,0);
- for (i=0; i<nmsg[0]; ++i) { j=(int)textwidth(msg[i]); if (j>len) len=j; }
- nx1=nmsg[1]-5; nx2=nmsg[1]+5+len; ny1=nmsg[2]-12; ny2=nmsg[2]+nmsg[0]*12+5;
- pol[0]=nx1; pol[1]=ny1; pol[2]=nx2; pol[3]=ny1; pol[4]=nx2;
- pol[5]=ny2; pol[6]=nx1; pol[7]=ny2; pol[8]=nx1; pol[9]=ny1;
- fillpoly(4,pol); drawpoly(5,pol); nx1+=7; ny1+=15;
- fprintf(postfile,"/pstrz {currentpoint 3 2 roll dup stringwidth pop dup \
- \n zxx gt { /zxx exch def } { pop } ifelse show moveto 0 -15 rmoveto \
- } bind def\n");
- fprintf(postfile,"%G /xbeg exch def %G /ybeg exch def 0 /zxx exch def xbeg \
- ybeg moveto\n",(double)(nmsg[1]),(double)(485-nmsg[2]));
- for (i=0; i<nmsg[0]; ++i)
- { outtextxy(nx1,ny1,msg[i]); ny1+=15;
- fprintf(postfile,"(%s) pstrz\n",msg[i]);
- }
- fprintf(postfile," currentpoint ybeg exch sub 15 add /dyzsv exch def \
- \n pop 1 setgray xbeg ybeg moveto zxx 20 add /zxx exch def xbeg 10\
- \n sub ybeg 20 add moveto zxx 0 rlineto 0 dyzsv neg rlineto zxx neg 0\
- \n rlineto closepath fill 0 setgray xbeg 10 sub ybeg 20 add moveto \
- \n zxx 0 rlineto 0 dyzsv neg rlineto zxx neg 0 rlineto 0 dyzsv rlineto\
- stroke xbeg ybeg moveto\n");
- for (i=0; i<nmsg[0]; ++i) fprintf(postfile,"(%s) pstrz\n",msg[i]);
- }
- /*************************************************************************
- * HPLTIT - Routine to get plot hardcopy on the HP LaserJet.
- *************************************************************************/
- void hpltit(FILE *hpfile)
- { int j,k;
- unsigned segment;
- unsigned char ch, bcn[]={
- /* Reset and position cursor at 600,400 dots x,y. bcn[0] - bcn[12] */
- 0x1B,0x45,0x1B,0X2A,0x70,0x36,0x30,0x30,0x78,0x34,0x30,0x30,0x59,
- /* Initiate raster graphics at 150 dots per inch. bcn[13] - bcn[19] */
- 0x1B,0x2A,0x74,0x31,0x35,0x30,0x52,
- /* Start a row of graphics at current left margin. bcn[20] - bcn[24] */
- 0x1B,0x2A,0x72,0x31,0x41,
- /* Transfer 80 bytes of raster graphics data. bcn[25] - bcn[30] */
- 0x1B,0x2A,0x62,0x38,0x30,0x57,
- /* End graphics, reset and form feed (not needed) bcn[31] - bcn[37] */
- 0x1B,0x2A,0x72,0x42,0x1B,0x45,0x0C};
-
- /* The graphics controller must be set to plane 0 to read the pixels in memory
- * starting at the graphics location A000:0000. The Turbo C graphics output
- * routines apparently leave it in that state, although it would obviously
- * be preferable to assure that with the ASM operator out.
- */
- segment=0xa000;
- for (k=0; k<20; ++k) fputc(bcn[k],hpfile); /* HP graphics header */
- for (j=0; j<480; ++j)
- {
- for (k=20; k<31; ++k) fputc(bcn[k],hpfile); /* HP graphics row */
- for (k=0; k<80; ++k) { ch=(unsigned char)peek(segment,j*80+k); fputc(ch,hpfile); }
- }
- for (k=31; k<37; ++k) fputc(bcn[k],hpfile); /* End HP graphics */
- } /* End HPLTIT */
- /********************* END FILE SPLOT.C **********************/
-
-
-
-